﻿using System;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Web;

using Blog.Framework.Models;
using Blog.Framework.Utility;

namespace Blog.Framework.DataAccess
{
    public class DataProvider : IDataProvider, IDisposable
    {
        BusinessObjectProvider mBusinessObjectProvider;

        public DataProvider(BusinessObjectProvider businessObjectProvider)
        {
            mBusinessObjectProvider = businessObjectProvider;
        }

        public DataProvider()
            : this(Reflection.CreateClass<BusinessObjectProvider>(Configuration.GetConfiguration<BlogConfigurationHandler>("BlogSettings").BusinessObjectProvider))
        {
        }

        public PagedList<PostSummary> GetRecentPostSummary(int index, int postsPerPage)
        {
            return mBusinessObjectProvider.GetRecentPostSummary(index, postsPerPage);
        }

        public PagedList<PostSummary> GetPostsForTag(string tag, int index, int postsPerPage)
        {
            return mBusinessObjectProvider.GetPostsForTag(tag, index, postsPerPage);
        }

        public PagedList<PostSummary> GetPostsForMonth(int month, int year, int index, int postsPerPage)
        {
            return mBusinessObjectProvider.GetPostsForMonth(month, year, index, postsPerPage);
        }

        public Post GetPostForUrl(string url)
        {
            return mBusinessObjectProvider.GetPostForUrl(url);
        }

        public PagedList<ArchiveCount> GetRecentArchiveCounts(int numberOfCounts)
        {
            return mBusinessObjectProvider.GetRecentArchiveCounts(numberOfCounts);
        }

        public List<ArchiveCount> GetArchiveCounts()
        {
            return mBusinessObjectProvider.GetArchiveCounts();
        }

        public List<TagWeight> GetTagCloud()
        {
            List<TagWeight> tags = mBusinessObjectProvider.GetTagWeights();
            List<double> counts = new List<double>();
            tags.ForEach(t => counts.Add(Convert.ToDouble(t.Count)));

            double mean;
            double stdDev = Statistics.StdDev(counts, out mean);

            foreach (TagWeight t in tags)
            {
                t.Factor = (t.Count - mean) / stdDev;
                t.Weight = ComputeWeight(t.Factor, stdDev);
            }

            return tags;
        }

        private int ComputeWeight(double factor, double stdDev)
        {
            if (factor <= -2 * stdDev)
                return 1;
            if (factor <= -1 * stdDev)
                return 2;
            if (factor <= -0.5 * stdDev)
                return 3;
            if (factor < 0.5 * stdDev)
                return 4;
            if (factor < 1 * stdDev)
                return 5;
            if (factor < 2 * stdDev)
                return 6;
            return 7;
        }

        void Dispose()
        {
            IDisposable disposable = mBusinessObjectProvider as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }

        void IDisposable.Dispose()
        {
            Dispose();
        }    
    }
}
